home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / PlayerPRO 4.5.1 / Plug-Ins / Import⁄Export Plugs / Mod.c < prev    next >
Text File  |  1995-11-03  |  22KB  |  770 lines

  1. /********************                        ***********************/
  2. //
  3. //    Player PRO 4.5x -- MOD to MADx & MADx to MOD
  4. //
  5. //    Version 1.0    - 12.3.95 ANR
  6. //
  7. //    To use with CodeWarrior 68K or PPC
  8. //
  9. //    Antoine ROSSET
  10. //    16 Tranchees
  11. //    1206 GENEVA
  12. //    SWITZERLAND
  13. //    
  14. //    FAX:            (+41 22) 346 11 97
  15. //    Compuserve:        100277,164
  16. //    Internet:         rosset@dial.eunet.ch
  17. //
  18. /********************                        ***********************/
  19.  
  20. #include "MOD.h"
  21. #include "RDriver.h"
  22.  
  23. #if defined(powerc) || defined(__powerc)
  24. enum {
  25.         PlayerPROPlug = kCStackBased
  26.         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  27.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( OSType)))
  28.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( Ptr*)))
  29.         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof( MADPartition*)))
  30.         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( PPInfoRec*)))
  31. };
  32.  
  33. ProcInfoType __procinfo = PlayerPROPlug;
  34. #else
  35. #include <A4Stuff.h>
  36. #endif
  37.  
  38.  
  39. static     short                MODTuning[ 65] =
  40.                         {
  41.  
  42.                         // -> Tuning 0
  43.                         
  44.                             1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  45.                             856,808,762,720,678,640,604,570,538,508,480,453,
  46.                             428,404,381,360,339,320,302,285,269,254,240,226,
  47.                             214,202,190,180,170,160,151,143,135,127,120,113,
  48.                             107,101,95,90,85,80,75,71,67,63,60,56
  49.                         };
  50.  
  51. short FoundNote( short Period)
  52. {
  53. short note;
  54.  
  55.     note = 0xFF;
  56.     if(Period != 0)
  57.     {
  58.         for(note = 0;note < 60;note++){
  59.             if(Period >= MODTuning[ note]) break;
  60.         }
  61.         if(note >= NUMBER_NOTES) note = 0xFF;
  62.     }
  63.  
  64.     if( note != 0xFF) note += 24;
  65.  
  66.     return note;
  67. }
  68.  
  69. Cmd* GetMADCommand( register short PosX, register short    TrackIdX, register PatData*    tempMusicPat)
  70. {
  71.     if( PosX < 0) PosX = 0;
  72.     else if( PosX >= tempMusicPat->header.size) PosX = tempMusicPat->header.size -1;
  73.         
  74.     return( & (tempMusicPat->Cmds[ (tempMusicPat->header.size * TrackIdX) + PosX]));
  75. }
  76.  
  77. void pStrcpy(register unsigned char *s1, register unsigned char *s2)
  78. {
  79.     register short len, i;
  80.     
  81.     len = *s2;
  82.     for ( i = 0; i <= len; i++) s1[ i] = s2[ i];
  83. }
  84.  
  85. void AnalyseSignatureMOD( long temp, short *maxInstru, long *PatternSize, short *tracksNo, MODDef* aMOD)
  86. {
  87.     long         test, i;
  88.     Boolean        result;
  89.  
  90.     *maxInstru = 31;
  91.  
  92.     switch( temp)
  93.     {
  94.         case 'FLT4':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  95.         case 'FLT8':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  96.         case 'M.K.':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  97.         case '5CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 5L;    *tracksNo = 5;    break;
  98.         case '6CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 6L;    *tracksNo = 6;    break;
  99.         case '7CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 7L;    *tracksNo = 7;    break;
  100.         case '8CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 8L;    *tracksNo = 8;    break;
  101.         case '9CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 9L;    *tracksNo = 9;    break;
  102.         case '10CH':    *PatternSize = sizeof( struct MODCom) * 64L * 10L;    *tracksNo = 10;    break;
  103.         case '11CH':    *PatternSize = sizeof( struct MODCom) * 64L * 11L;    *tracksNo = 11;    break;
  104.         case '12CH':    *PatternSize = sizeof( struct MODCom) * 64L * 12L;    *tracksNo = 12;    break;
  105.         case '13CH':    *PatternSize = sizeof( struct MODCom) * 64L * 13L;    *tracksNo = 13;    break;
  106.         case '14CH':    *PatternSize = sizeof( struct MODCom) * 64L * 14L;    *tracksNo = 14;    break;
  107.         case '15CH':    *PatternSize = sizeof( struct MODCom) * 64L * 15L;    *tracksNo = 15;    break;
  108.         case '16CH':    *PatternSize = sizeof( struct MODCom) * 64L * 16L;    *tracksNo = 16;    break;
  109.         case '17CH':    *PatternSize = sizeof( struct MODCom) * 64L * 17L;    *tracksNo = 17;    break;
  110.         case '18CH':    *PatternSize = sizeof( struct MODCom) * 64L * 18L;    *tracksNo = 18;    break;
  111.         case '19CH':    *PatternSize = sizeof( struct MODCom) * 64L * 19L;    *tracksNo = 19;    break;
  112.         case '20CH':    *PatternSize = sizeof( struct MODCom) * 64L * 20L;    *tracksNo = 20;    break;
  113.         case '21CH':    *PatternSize = sizeof( struct MODCom) * 64L * 21L;    *tracksNo = 21;    break;
  114.         case '22CH':    *PatternSize = sizeof( struct MODCom) * 64L * 22L;    *tracksNo = 22;    break;
  115.         case '23CH':    *PatternSize = sizeof( struct MODCom) * 64L * 23L;    *tracksNo = 23;    break;
  116.         case '24CH':    *PatternSize = sizeof( struct MODCom) * 64L * 24L;    *tracksNo = 24;    break;
  117.         case '25CH':    *PatternSize = sizeof( struct MODCom) * 64L * 25L;    *tracksNo = 25;    break;
  118.         case '26CH':    *PatternSize = sizeof( struct MODCom) * 64L * 26L;    *tracksNo = 26;    break;
  119.         case '27CH':    *PatternSize = sizeof( struct MODCom) * 64L * 27L;    *tracksNo = 27;    break;
  120.         case '28CH':    *PatternSize = sizeof( struct MODCom) * 64L * 28L;    *tracksNo = 28;    break;
  121.         case '29CH':    *PatternSize = sizeof( struct MODCom) * 64L * 29L;    *tracksNo = 29;    break;
  122.         case '30CH':    *PatternSize = sizeof( struct MODCom) * 64L * 30L;    *tracksNo = 30;    break;
  123.         case '31CH':    *PatternSize = sizeof( struct MODCom) * 64L * 31L;    *tracksNo = 31;    break;
  124.         case '32CH':    *PatternSize = sizeof( struct MODCom) * 64L * 32L;    *tracksNo = 32;    break;
  125.         
  126.         default:
  127.             *PatternSize     = sizeof( struct MODCom) * 64L * 4L;            *tracksNo = 4;
  128.             
  129.             result = true;
  130.             test = 0;
  131.             for( i = 0; i < 15; i++)
  132.             {
  133.                 test += aMOD->fid[i].numWords;
  134.                 if( aMOD->fid[i].fineTune > 0x0F) result = false;
  135.             }
  136.             if( test == 0) result = false;
  137.                         
  138.             if( result) *maxInstru         = 15;
  139.             else *maxInstru             = 0;
  140.         break;
  141.     }
  142. }
  143.  
  144. struct MODCom* GetMODCommand( short position, short whichTracks, short whichPattern, short maxTracks, Ptr PatPtr)
  145. {
  146.     struct MODCom*    myMODCom;
  147.     
  148.     myMODCom =    (struct MODCom*) (PatPtr +
  149.                 whichPattern * 64L * sizeof( struct MODCom) * maxTracks +
  150.                 position * sizeof( struct MODCom) * maxTracks +
  151.                 whichTracks * sizeof( struct MODCom));
  152.     
  153.     return myMODCom;
  154. }
  155.  
  156. OSErr PPConvertMod2Mad( Ptr aMOD,long MODSize, MADPartition    *theMAD)
  157. {
  158.     short             i, PatMax, x, tracksNo, z, maxInstru;
  159.     long             sndSize, OffSetToSample, MPatSize, temp, inOutCount;
  160.     Ptr                MaxPtr;
  161.     OSErr            theErr;
  162.     Ptr                theInstrument[ 64], destPtr;
  163.     long             finetune[16] = 
  164.     {
  165.         8363,    8413,    8463,    8529,    8581,    8651,    8723,    8757,
  166.         7895,    7941,    7985,    8046,    8107,    8169,    8232,    8280
  167.     };
  168.     /**** Variables for MAD File *****/
  169.     Cmd                    *aCmd;
  170.  
  171.     /**** Variables for MOD File *****/
  172.     MODDef                 *theMOD;
  173.     struct MODPat        *PatInt;
  174.     MODDef                *MODInt;
  175.     struct MODCom        *theCommand;
  176.     /********************************/
  177.     
  178.     theMOD = ((MODDef*) aMOD);
  179.     MaxPtr = (Ptr)((long) theMOD + MODSize);
  180.  
  181.     temp = *((long*)(aMOD + 0x438));        // Signature...
  182.  
  183.     AnalyseSignatureMOD( temp, &maxInstru, &MPatSize, &tracksNo, theMOD);
  184.     
  185.     if( maxInstru == 0)
  186.     {
  187.         return MADFileNotSupportedByThisPlug;    // This file is NOT a Mod file !!!!!! This should NEVER happen !
  188.     }
  189.     else if( maxInstru == 15)                // Old Mods format with 15 instruments
  190.     {
  191.         MODInt = (MODDef*) ( (Ptr) theMOD - (Ptr) 0x1E0);
  192.         PatInt = (struct MODPat*) ((Ptr) MODInt->patterns - (Ptr) 0x4);
  193.         
  194.         PatMax = 0;
  195.         for(i=0; i<128; i++)
  196.         {
  197.             if( MODInt->oPointers[i] < 0) MODInt->oPointers[i] = 0;
  198.             if( MODInt->oPointers[i] > 128) MODInt->oPointers[i] = 0;
  199.         
  200.             if( MODInt->oPointers[i] >= PatMax)    PatMax = MODInt->oPointers[i];
  201.         }
  202.         PatMax++;
  203.         
  204.     //    if( MODInt->numPointers > 64) MODInt->numPointers = 64;
  205.     //    for(i=64; i<128; i++) MODInt->oPointers[i] = 0;
  206.         
  207.         OffSetToSample = (long) 0x258 + PatMax * MPatSize;
  208.     }
  209.     else                                    // Mods format with 32 instruments
  210.     {
  211.         MODInt    = theMOD;
  212.         PatInt    = MODInt->patterns;
  213.     
  214.         PatMax = 0;
  215.         for(i=0; i<128; i++)
  216.         {
  217.             if( MODInt->oPointers[i] < 0) MODInt->oPointers[i] = 0;
  218.             if( MODInt->oPointers[i] > 128) MODInt->oPointers[i] = 0;
  219.             
  220.             if( MODInt->oPointers[i] >= PatMax) PatMax = MODInt->oPointers[i];
  221.         }
  222.         PatMax++;
  223.         
  224.         OffSetToSample = (long) 0x43c + PatMax * MPatSize;
  225.     }
  226.     
  227.     for( i = 0; i < maxInstru ; i++)
  228.     {
  229.         theInstrument[i] = (Ptr) ((long) theMOD + (long) OffSetToSample);
  230.  
  231.         sndSize = ((long) theMOD->fid[i].numWords) * 2L;
  232.     
  233.         if( theInstrument[i] + sndSize > MaxPtr)
  234.         {
  235.             theMOD->fid[i].numWords = MaxPtr - theInstrument[i];
  236.             theMOD->fid[i].numWords /= 2L;
  237.             
  238.             if( theMOD->fid[i].numWords < 0) theMOD->fid[i].numWords = 0;
  239.                     
  240.             sndSize = ((long) theMOD->fid[i].numWords) * 2L;
  241.         }
  242.         
  243.         OffSetToSample += sndSize;
  244.  
  245.         if( theMOD->fid[i].loopWords > 2 && sndSize > 0)
  246.         {
  247.             if( (long) theMOD->fid[i].loopWord +
  248.                 (long) theMOD->fid[i].loopWords > 
  249.                 (long) theMOD->fid[i].numWords)
  250.             {
  251.                 theMOD->fid[ i].loopWords =    (long) theMOD->fid[i].numWords -
  252.                                             (long) theMOD->fid[i].loopWord;
  253.         
  254.                 if( (long) theMOD->fid[i].loopWord +
  255.                 (long) theMOD->fid[i].loopWords > 
  256.                 (long) theMOD->fid[i].numWords)
  257.                 {
  258.                     theMOD->fid[i].loopWord = 0;
  259.                     theMOD->fid[i].loopWords = 0;
  260.                 }
  261.             }
  262.         }
  263.         else
  264.         {
  265.             theMOD->fid[i].loopWord = 0;
  266.             theMOD->fid[i].loopWords = 0;
  267.         }
  268.     }
  269.     
  270.     /***************************************************************/
  271.     /******** MOD is ready to be converted into MAD File ***********/
  272.     /***************************************************************/
  273.     
  274.     inOutCount = sizeof( MADSpec);
  275.     theMAD->header = (MADSpec*) NewPtrClear( inOutCount);    
  276.     if( theMAD->header == 0L) return MADNeedMemory;
  277.     
  278.     theMAD->header->MAD = 'MADH';
  279.     
  280.     for(i=0; i<22; i++) theMAD->header->name[i] = theMOD->NameSignature[i];
  281.     
  282.     theMAD->header->tempo = 125;
  283.     theMAD->header->speed = 6;
  284.     theMAD->header->numPat = PatMax;
  285.     theMAD->header->numPointers = MODInt->numPointers;
  286.     
  287.     for(i=0; i<128; i++) theMAD->header->oPointers[ i] = MODInt->oPointers[ i];
  288.     
  289.     theMAD->header->numChn = tracksNo;
  290.  
  291.     for(i = 0; i < maxInstru; i++)
  292.     {
  293.         for( x = 0; x < 22; x++) theMAD->header->fid[i].name[x] = theMOD->fid[i].Filename[x];
  294.         theMAD->header->fid[i].type = 0;
  295.         
  296.         if( theMOD->fid[ i].numWords > 0)
  297.         {
  298.             sData    *curData;
  299.             
  300.             theMAD->header->fid[i].numSamples = 1;
  301.             
  302.             curData = theMAD->sample[ i][ 0] = (sData*) NewPtrClear( sizeof( sData));
  303.             
  304.             curData->size        = theMOD->fid[i].numWords * 2L;
  305.             curData->loopBeg     = theMOD->fid[i].loopWord*2L;
  306.             curData->loopSize     = theMOD->fid[i].loopWords*2L;
  307.             curData->vol        = theMOD->fid[i].volume;
  308.             curData->c2spd        = finetune[ theMOD->fid[i].fineTune];
  309.             curData->loopType    = 0;
  310.             curData->amp        = 8;
  311.             curData->panning    = 0;
  312.             curData->relNote    = 0;
  313.         //    for( x = 0; x < 22; x++) curData->name[x] = theMOD->fid[ i].Filename[ x];
  314.             
  315.             
  316.             curData->data         = NewPtr( curData->size);
  317.             if( curData->data == 0L) return MADNeedMemory;
  318.                 
  319.             BlockMove( theInstrument[i], curData->data, curData->size);
  320.         }
  321.         else theMAD->header->fid[ i].numSamples = 0;
  322.     }
  323.     
  324.     for( i = maxInstru; i < MAXINSTRU ; i++)
  325.     {
  326.         theMAD->header->fid[ i].numSamples = 0;
  327.     }
  328.     
  329.     for(i=0; i<theMAD->header->numPat; i++)
  330.     {
  331.         theMAD->partition[ i] = (PatData*) NewPtrClear( sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd));
  332.         if( theMAD->partition[ i] == 0L) return MADNeedMemory;
  333.         
  334.         theMAD->partition[ i]->header.size         = 64L;
  335.         theMAD->partition[ i]->header.compMode     = 'NONE';
  336.         
  337.         for( x = 0; x < 20; x++) theMAD->partition[ i]->header.name[ x] = 0;
  338.         
  339.         theMAD->partition[ i]->header.patBytes = 0L;        theMAD->partition[ i]->header.unused2 = 0L;
  340.     
  341.         MaxPtr = (Ptr) theMAD->partition[ i];
  342.         MaxPtr += sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd);
  343.  
  344.         for(x=0; x<64; x++)
  345.         {
  346.             for(z=0; z<theMAD->header->numChn; z++)
  347.             {
  348.                 aCmd = GetMADCommand(  x,  z, theMAD->partition[ i]);
  349.                 if( (Ptr) aCmd + sizeof( Cmd) > MaxPtr) DebugStr("\pConversion ERROR");
  350.                 
  351.                 theCommand     = GetMODCommand(    x,
  352.                                                 z,
  353.                                                 i,
  354.                                                 theMAD->header->numChn,
  355.                                                 (Ptr) PatInt);
  356.                 
  357.                 aCmd->ins = (theCommand->InstrLoNibble & 0x0F) + (theCommand->InstrHiNibble << 4);
  358.                 aCmd->note = FoundNote( theCommand->AmigaPeriod);
  359.                 
  360.                 aCmd->cmd = theCommand->EffectCmd & 0x0F;
  361.                 
  362.                 if( aCmd->cmd == 0x0C)
  363.                 {
  364.                     aCmd->vol    = 0x10 + (theCommand->EffectArg & 0x00FF);
  365.                     if( aCmd->arg > 0x50) aCmd->vol = 0x50;
  366.                     aCmd->cmd     = 0;
  367.                     aCmd->arg     = 0;
  368.                 }
  369.                 else
  370.                 {
  371.                     aCmd->cmd     = theCommand->EffectCmd & 0x0F;
  372.                     aCmd->arg     = theCommand->EffectArg & 0x00FF;
  373.                     aCmd->vol    = 0xFF;
  374.                 }
  375.             }
  376.         }
  377.     }
  378.     for( i = theMAD->header->numPat; i < MAXPATTERN ; i++) theMAD->partition[ i] = 0L;
  379.  
  380.     return noErr;
  381. }
  382.  
  383. Ptr PPConvertMad2Mod( MADPartition *theMAD)
  384. {
  385.     short                 i, x, z, maxInstru;
  386.     long                 sndSize, OffSetToSample, temp, InstruSize, *alpha;
  387.     Ptr                    MaxPtr;
  388.     OSErr                theErr;
  389.     Ptr                    theInstrument[ 64], destPtr;
  390.     Boolean                CheckGoodMod;
  391.     Str255                tempStr;
  392.     char                redut[4];
  393.     short                MODTuning[ 65] =
  394.                     /*    {    0,
  395.                             1712,1616,1525,1440,1357,1281,1209,1141,1077,1017, 961, 907,
  396.                             856,808,762,720,678,640,604,570,538,508,480,453,
  397.                             428,404,381,360,339,320,302,285,269,254,240,226,
  398.                             214,202,190,180,170,160,151,143,135,127,120,113,
  399.                             107,101, 95, 90, 85, 80, 76, 71, 67, 64, 60, 57 };*/
  400.                             
  401.                         {
  402.  
  403.                         // -> Tuning 0
  404.                         
  405.                             1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  406.                             856,808,762,720,678,640,604,570,538,508,480,453,
  407.                             428,404,381,360,339,320,302,285,269,254,240,226,
  408.                             214,202,190,180,170,160,151,143,135,127,120,113,
  409.                             107,101,95,90,85,80,75,71,67,63,60,56
  410.                         };
  411.                             
  412.     /**** Variables for MAD file ****/
  413.     
  414.     Cmd                    *aCmd;
  415.  
  416.     /**** Variables for MOD file ****/
  417.     
  418.     MODDef                 *theMOD;
  419.     struct MODCom        *theCommand;
  420.     /********************************/
  421.  
  422.     maxInstru = 31;
  423.         
  424.     InstruSize = 0;
  425.     for( i = 0; i < maxInstru ; i++)
  426.     {
  427.         if( theMAD->header->fid[ i].numSamples > 0)
  428.         {
  429.             theInstrument[ i]    = theMAD->sample[ i][ 0]->data;
  430.             InstruSize            += theMAD->sample[ i][ 0]->size;
  431.         }
  432.     }
  433.     
  434.     /******** MAD is ready to be converted **********/
  435.     /******** Copy information in the MOD file    ***/
  436.     
  437.     theMOD = (MODDef*) NewPtr( 0x43c + InstruSize + theMAD->header->numChn * 64L * theMAD->header->numPat * sizeof( struct MODCom));
  438.     if( theMOD == 0L) return 0L;
  439.     
  440.     theMOD->longFmtSignature = 'M.K.';
  441.     if( theMAD->header->numChn > 4)
  442.     {
  443.         NumToString( theMAD->header->numChn, tempStr);
  444.         if( tempStr[ 0] == 2)
  445.         {
  446.             redut[0] = tempStr[1];
  447.             redut[1] = tempStr[2];
  448.             redut[2] = 'C';
  449.             redut[3] = 'H';
  450.         }
  451.         else if( tempStr[ 0] == 1)
  452.         {
  453.             redut[0] = tempStr[1];
  454.             redut[1] = 'C';
  455.             redut[2] = 'H';
  456.             redut[3] = 'N';
  457.         }
  458.         
  459.         alpha = (long*) redut;
  460.         
  461.         theMOD->longFmtSignature = *alpha;
  462.     }
  463.     
  464.     MaxPtr = (Ptr) theMOD + GetPtrSize( (Ptr) theMOD);
  465.     
  466.     for(i=0; i<20; i++) theMOD->NameSignature[i] = theMAD->header->name[i];
  467.     
  468.     CheckGoodMod = false;
  469.     theMOD->numPointers = theMAD->header->numPointers;
  470.     for(i=0; i<128; i++)
  471.     {
  472.         theMOD->oPointers[ i] = theMAD->header->oPointers[ i];
  473.         if( theMOD->oPointers[ i] == theMAD->header->numPat - 1) CheckGoodMod = true;
  474.     }
  475.     if( !CheckGoodMod) theMOD->oPointers[ theMOD->numPointers + 1] = theMAD->header->numPat - 1;
  476.     
  477.     for(i=0; i<maxInstru; i++)
  478.     {
  479.         if( theMAD->header->fid[ i].numSamples > 0)
  480.         {
  481.             sData    *curData = theMAD->sample[ i][ 0];
  482.             short    temp;
  483.         
  484.             for( x = 0; x < 22; x++) theMOD->fid[i].Filename[x] = theMAD->header->fid[i].name[x];
  485.             
  486.             if( curData->size/2L > 0xFFFFUL) theMOD->fid[i].numWords = 0xFFFFUL;
  487.             else theMOD->fid[i].numWords = (short) (curData->size / 2L);
  488.             
  489.             temp = (curData->c2spd - NOFINETUNE) / 50;
  490.             if( temp < 0) temp += 16;
  491.             
  492.             theMOD->fid[i].fineTune = temp;
  493.             
  494.             theMOD->fid[i].volume         = curData->vol;
  495.             theMOD->fid[i].loopWord     = curData->loopBeg / 2L;
  496.             theMOD->fid[i].loopWords     = curData->loopSize / 2L;
  497.         }
  498.         else
  499.         {
  500.             for( x = 0; x < 22; x++) theMOD->fid[i].Filename[x] = 0;
  501.             
  502.             theMOD->fid[i].numWords     = 0;
  503.             theMOD->fid[i].fineTune     = 0;
  504.             theMOD->fid[i].volume         = 64;
  505.             theMOD->fid[i].loopWord     = 0;
  506.             theMOD->fid[i].loopWords     = 0;
  507.         }
  508.     }
  509.     
  510.     InstruSize = 0L;
  511.     
  512.     OffSetToSample = (long) 0x43c + theMAD->header->numPat * sizeof( struct MODCom) * 64L * theMAD->header->numChn;
  513.     
  514.     for(i=0; i<maxInstru; i++)
  515.     {
  516.         destPtr = (Ptr) ((long) theMOD + (long) OffSetToSample + (long) InstruSize);
  517.     
  518.         if( destPtr  + (long) (theMOD->fid[i].numWords) * 2L <= MaxPtr) BlockMove( theInstrument[i], destPtr, (long) (theMOD->fid[i].numWords) * 2L);
  519.         else DebugStr("\pInstrument Error");
  520.         
  521.         InstruSize += (long) (theMOD->fid[i].numWords) * 2L;
  522.     }
  523.     
  524.     for(i=0; i<theMAD->header->numPat; i++)
  525.     {
  526.         for(x=0; x < 64; x++)
  527.         {
  528.             for(z=0; z < theMAD->header->numChn; z++)
  529.             {
  530.                 aCmd         = GetMADCommand(     x,
  531.                                                 z,
  532.                                                 theMAD->partition[ i]);
  533.                 
  534.                 theCommand     = GetMODCommand(    x,
  535.                                                 z,
  536.                                                 i,
  537.                                                 theMAD->header->numChn,
  538.                                                 (Ptr) theMOD->patterns);
  539.                                                 
  540.                 if( (Ptr) theCommand > MaxPtr) DebugStr("\pCommand Error");
  541.                 
  542.                 theCommand->InstrLoNibble = (aCmd->ins & 0x0F);
  543.                 theCommand->InstrHiNibble = (aCmd->ins >> 4);
  544.                 
  545.                 if( aCmd->note != 0xFF) theCommand->AmigaPeriod = MODTuning[ aCmd->note - 24];
  546.                 else theCommand->AmigaPeriod = 0;
  547.                 
  548.                 theCommand->EffectCmd = aCmd->cmd;
  549.                 theCommand->EffectArg = aCmd->arg;
  550.                 
  551.                 if( aCmd->vol != 0xFF && theCommand->EffectCmd == 0 && theCommand->EffectArg == 0)
  552.                 {
  553.                     theCommand->EffectCmd = volumeE;
  554.                     theCommand->EffectArg = aCmd->vol - 0x10;
  555.                 }
  556.             }
  557.         }
  558.     }
  559.     
  560.     return( (Ptr) theMOD);
  561. }
  562.  
  563. OSErr ExtractMODInfo( PPInfoRec *info, Ptr AlienFile)
  564. {
  565.     MODDef    *myMOD = ( MODDef*) AlienFile;
  566.     long    PatternSize;
  567.     short    i;
  568.     short    maxInstru;
  569.     short    tracksNo;
  570.     
  571.     /*** Signature ***/
  572.     
  573.     info->signature = myMOD->longFmtSignature;
  574.     
  575.     /*** Internal name ***/
  576.     
  577.     myMOD->NameSignature[ 19] = '\0';
  578.     pStrcpy( info->internalFileName, CtoPstr( myMOD->NameSignature));
  579.  
  580.     /*** Check MOD Type ***/
  581.     
  582.     AnalyseSignatureMOD( info->signature, &maxInstru, &PatternSize, &info->totalTracks, myMOD);
  583.     if( maxInstru == 0)
  584.     {
  585.         return MADFileNotSupportedByThisPlug;
  586.     }
  587.     else if( maxInstru == 15)    // Old mod format
  588.     {
  589.         info->signature = '----';
  590.         myMOD = (MODDef*) ((Ptr) myMOD - (Ptr) 0x1E0);
  591.     }
  592.     
  593.     /*** Total Patterns ***/
  594.     
  595.     info->totalPatterns = 0;
  596.     for( i = 0; i < 128; i++)
  597.     {
  598.         if( myMOD->oPointers[ i] >= info->totalPatterns)    info->totalPatterns = myMOD->oPointers[ i];
  599.     }
  600.     info->totalPatterns++;
  601.     
  602.     /*** Partition Length ***/
  603.     
  604.     info->partitionLength = myMOD->numPointers;
  605.     
  606.     /*** Total Instruments ***/
  607.     
  608.     for( i = 0, info->totalInstruments = 0; i < maxInstru ; i++)
  609.     {
  610.         if( myMOD->fid[ i].numWords > 5) info->totalInstruments++;
  611.     }
  612.     
  613.     pStrcpy( info->formatDescription, "\pMOD Plug");
  614.  
  615.     return noErr;
  616. }
  617.  
  618. OSErr TestMODFile( Ptr AlienFile)
  619. {
  620.     short    maxInstru;
  621.     long    PatternSize;
  622.     short    tracksNo;
  623.     
  624.     AnalyseSignatureMOD( *((long*)(AlienFile + 0x438)), &maxInstru, &PatternSize, &tracksNo, (MODDef*) AlienFile);
  625.     
  626.     if( maxInstru == 0) return MADFileNotSupportedByThisPlug;
  627.     else return noErr;
  628. }
  629.  
  630.  
  631. /*****************/
  632. /* MAIN FUNCTION */
  633. /*****************/
  634.  
  635. OSErr main( OSType order, FSSpec *AlienFileFSSpec, MADPartition *MadFile, PPInfoRec *info)
  636. {
  637.     OSErr    myErr;
  638.     Ptr        AlienFile;
  639.     short    vRefNum, iFileRefI;
  640.     long    dirID, sndSize;
  641.     
  642. #ifndef powerc
  643.     long    oldA4 = SetCurrentA4();             //this call is necessary for strings in 68k code resources
  644. #endif
  645.  
  646.     HGetVol( 0L, &vRefNum, &dirID);
  647.     HSetVol( 0L, AlienFileFSSpec->vRefNum, AlienFileFSSpec->parID);
  648.  
  649.     myErr = noErr;
  650.  
  651.     switch( order)
  652.     {
  653.         case 'IMPL':
  654.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  655.             if( myErr == noErr)
  656.             {
  657.                 GetEOF( iFileRefI, &sndSize);
  658.             
  659.                 // ** MEMORY Test Start
  660.                 AlienFile = NewPtr( sndSize * 2L);
  661.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  662.                 // ** MEMORY Test End
  663.                 
  664.                 else
  665.                 {
  666.                     DisposPtr( AlienFile);
  667.                     
  668.                     AlienFile = NewPtr( sndSize);
  669.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  670.                     if( myErr == noErr)
  671.                     {
  672.                         myErr = TestMODFile( AlienFile);
  673.                         if( myErr == noErr)
  674.                         {
  675.                             myErr = PPConvertMod2Mad( AlienFile, GetPtrSize( AlienFile), MadFile);
  676.                         }
  677.                     }
  678.                     DisposPtr( AlienFile);    AlienFile = 0L;
  679.                 }
  680.                 FSClose( iFileRefI);
  681.             }
  682.         break;
  683.         
  684.         case 'TEST':
  685.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  686.             if( myErr == noErr)
  687.             {
  688.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  689.                 
  690.                 AlienFile = NewPtr( sndSize);
  691.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  692.                 else
  693.                 {
  694.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  695.                     myErr = TestMODFile( AlienFile);
  696.                     
  697.                     DisposPtr( AlienFile);    AlienFile = 0L;
  698.                 }
  699.                 FSClose( iFileRefI);
  700.             }
  701.         break;
  702.         
  703.         case 'EXPL':
  704.             AlienFile = PPConvertMad2Mod( MadFile);
  705.             
  706.             if( AlienFile != 0L)
  707.             {
  708.                 myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  709.                 if( myErr == fnfErr)
  710.                 {
  711.                     myErr = Create( AlienFileFSSpec->name, 0, 'SNPL', 'STrk');
  712.                     myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  713.                 }
  714.                 
  715.                 if( myErr == noErr)
  716.                 {
  717.                     FInfo    fndrInfo;
  718.                 
  719.                     sndSize = GetPtrSize( AlienFile);
  720.                     myErr = SetEOF( iFileRefI, sndSize);
  721.                     if( myErr == noErr)
  722.                     {
  723.                         myErr = FSWrite( iFileRefI, &sndSize, AlienFile);
  724.                     }
  725.                     FSClose( iFileRefI);
  726.                     
  727.                     GetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
  728.                     fndrInfo.fdCreator    = 'SNPL';
  729.                     fndrInfo.fdType        = 'STrk';
  730.                     SetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
  731.                 }
  732.                 DisposPtr( AlienFile);    AlienFile = 0L;
  733.             }
  734.         break;
  735.  
  736.         case 'INFO':
  737.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  738.             if( myErr == noErr)
  739.             {
  740.                 GetEOF( iFileRefI, &info->fileSize);
  741.             
  742.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  743.                 
  744.                 AlienFile = NewPtr( sndSize);
  745.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  746.                 else
  747.                 {
  748.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  749.                     if( myErr == noErr)
  750.                     {
  751.                         myErr = ExtractMODInfo( info, AlienFile);
  752.                     }
  753.                     DisposPtr( AlienFile);    AlienFile = 0L;
  754.                 }
  755.                 FSClose( iFileRefI);
  756.             }
  757.         break;
  758.         
  759.         default:
  760.             myErr = MADOrderNotImplemented;
  761.         break;
  762.     }
  763.  
  764.     HSetVol( 0L, vRefNum, dirID);
  765.  
  766.     #ifndef powerc
  767.         SetA4( oldA4);
  768.     #endif
  769.     return myErr;
  770. }